// #pragma once
// #include <cstdint>
// #include <cstring>
// #include <algorithm>
// #include <vector>
// #include <limits>
// #include "time_source.h"
//
// // ============== 工具：64-bit 主机/网络序转换 ==============
// #if defined(_WIN32)
//   #include <winsock2.h>
//   #include <ws2tcpip.h>
// #else
//   #include <arpa/inet.h>
// #endif
// static inline uint64_t htonll(uint64_t v){
// #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
//   return ( (uint64_t)htonl((uint32_t)(v & 0xffffffffULL)) << 32 ) | htonl((uint32_t)(v >> 32));
// #else
//   return v;
// #endif
// }
// static inline uint64_t ntohll(uint64_t v){
// #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
//   return ( (uint64_t)ntohl((uint32_t)(v & 0xffffffffULL)) << 32 ) | ntohl((uint32_t)(v >> 32));
// #else
//   return v;
// #endif
// }
//
// // ============== 合并后的报文格式 ==============
// // mode: 1=REQ（请求）, 2=RESP（应答）
// // 字段说明：
// //   k        = 轮次/计数戳（用于配对、乱序容忍）
// //   phi_s    = 发送端“节拍相位”（ns，对 tau 取模；REQ 中通常≈0）
// //   r_i_ppm  = 发送端当前频率校正（ppm，便于对端参考）
// //   t1_ns    = 请求端发送时刻（REQ填写）
// //   t2_ns    = 应答端接收时刻（RESP填写）
// //   t3_ns    = 应答端发送时刻（RESP填写）
// //   （t4 在请求端本地接收 RESP 时刻采样，不进包）
// #pragma pack(push, 1)
// struct SyncNtpMsg {
//   uint8_t   version{1};    // 预留协议版本
//   uint8_t   mode{0};       // 1=REQ  2=RESP
//   uint16_t  flags{0};      // 预留能力位（如是否HW戳、是否解模等）
//   uint32_t  k{0};          // 轮次编号
//   uint32_t  phi_s{0};      // 相位(ns, 0..tau)
//   int32_t   r_i_ppm{0};    // 发送端速率校正（ppm）
//   uint64_t  t1_ns{0};      // A 发送
//   uint64_t  t2_ns{0};      // B 接收
//   uint64_t  t3_ns{0};      // B 发送
//
//   // 序列化（主机->网络序）
//   void hton() {
//     k      = htonl(k);
//     phi_s  = htonl(phi_s);
//     r_i_ppm= htonl(static_cast<uint32_t>(r_i_ppm));
//     t1_ns  = htonll(t1_ns);
//     t2_ns  = htonll(t2_ns);
//     t3_ns  = htonll(t3_ns);
//     // version/mode/flags 不转（8/16bit在绝大多数协议里按网络序读写也OK）
//     flags  = htons(flags);
//   }
//   // 反序列化（网络->主机序）
//   void ntoh() {
//     k      = ntohl(k);
//     phi_s  = ntohl(phi_s);
//     r_i_ppm= static_cast<int32_t>(ntohl(static_cast<uint32_t>(r_i_ppm)));
//     t1_ns  = ntohll(t1_ns);
//     t2_ns  = ntohll(t2_ns);
//     t3_ns  = ntohll(t3_ns);
//     flags  = ntohs(flags);
//   }
//
//   static constexpr size_t size_bytes() { return sizeof(SyncNtpMsg); }
//
//   // ---------- 辅助构造 ----------
//   // 生成 REQ：k、tau_ns、当前频率校正（ppm）
//   static SyncNtpMsg make_req(uint32_t k, uint32_t tau_ns, int32_t r_i_ppm) {
//     SyncNtpMsg m;
//     m.version = 1;
//     m.mode    = 1; // REQ
//     m.k       = k;
//     m.r_i_ppm = r_i_ppm;
//     uint64_t now = TscSource::now_ns();
//     m.t1_ns   = now;
//     m.phi_s   = static_cast<uint32_t>(now % tau_ns); // 节拍相位（一般≈0）
//     return m;
//   }
//   // 根据对端 REQ 填写 RESP（在 B 上调用）
//   static SyncNtpMsg make_resp_from_req(const SyncNtpMsg& req) {
//     SyncNtpMsg m;
//     m.version = req.version;
//     m.mode    = 2; // RESP
//     m.k       = req.k;
//     m.r_i_ppm = 0;     // 可选：也回自己当前ppm
//     m.phi_s   = 0;     // RESP 不用相位也可
//     m.t1_ns   = req.t1_ns;               // 回显对端T1
//     m.t2_ns   = TscSource::now_ns();     // 我方接收戳
//     m.t3_ns   = TscSource::now_ns();     // 我方发送戳（尽量贴近send）
//     return m;
//   }
// };
// #pragma pack(pop)
//
// // ============== NTP 估计结果 ==============
// struct SyncNtpEstimate {
//   bool     ok{false};
//   uint32_t k{0};
//   int64_t  delay_ns{0};       // ((t2 - t1) + (t4 - t3))/2
//   int64_t  offset_ns{0};      // ((t2 - t1) - (t4 - t3))/2
//   int64_t  min_delay_ns{0};   // min-filter 结果（近似单向传播时延）
// };
//
// // ============== 简易估计器（带最小时延滤波） ==============
// // 用法：收到 RESP 后，调用 estimate_from_resp(resp, t4_ns) 得到 delay/offset；
// // 同时内部维护一个窗口最小 delay 作为单向时延近似（抗排队抖动）。
// class SyncNtpEstimator {
// public:
//   explicit SyncNtpEstimator(size_t min_win=32): win_(min_win) {}
//
//   // 估计（在请求端 A 上）：输入 RESP 报文和本地接收时刻 t4_ns
//   SyncNtpEstimate estimate_from_resp(const SyncNtpMsg& resp_net, uint64_t t4_ns,
//                                      uint64_t t1_fallback=0 /*可选：若没存本地t1*/ )
//   {
//     SyncNtpEstimate est{};
//     SyncNtpMsg m = resp_net;  // 拷贝以便 ntoh
//     m.ntoh();
//
//     // 优先用本地记录的 t1，如果外面传进来（比如你的 Net 类缓存了 t1）
//     uint64_t t1 = (t1_fallback!=0) ? t1_fallback : m.t1_ns;
//     if (m.mode!=2 || m.t2_ns==0 || m.t3_ns==0 || t1==0 || t4_ns==0) return est;
//
//     const int64_t d1 = (int64_t)(m.t2_ns - t1);
//     const int64_t d2 = (int64_t)(t4_ns - m.t3_ns);
//     const int64_t delay  = (d1 + d2) / 2;
//     const int64_t offset = (d1 - d2) / 2;
//
//     push_min_delay(delay);
//     est.ok           = true;
//     est.k            = m.k;
//     est.delay_ns     = delay;
//     est.offset_ns    = offset;
//     est.min_delay_ns = min_delay_ns();
//     return est;
//   }
//
//   // 最小时延
//   int64_t min_delay_ns() const {
//     if (buf_.empty()) return std::numeric_limits<int64_t>::max();
//     return *std::min_element(buf_.begin(), buf_.end());
//   }
//
//   void clear() { buf_.clear(); }
//
// private:
//   void push_min_delay(int64_t d){
//     if (d<=0) return;
//     buf_.push_back(d);
//     if (buf_.size()>win_) buf_.erase(buf_.begin());
//   }
//
//   size_t win_;
//   std::vector<int64_t> buf_;
// };
